import time
import sensor
import image
import utime
from image import SEARCH_EX
from machine import UART
from random import randint
from fpioa_manager import fm



sensor.reset()
sensor.set_contrast(1)
sensor.set_gainceiling(16)
sensor.set_framesize(sensor.QQVGA)
sensor.set_pixformat(sensor.RGB565)

clock = time.clock()

white = (61, 94, -74, 30, -20, 14)
black = (0, 15, -62, 11, -17, 12)

chess = [(44, 24, 24, 24), (68, 24, 24, 24), (92, 24, 24, 24),
         (44, 48, 24, 24), (68, 48, 24, 24), (92, 48, 24, 24),
         (44, 72, 24, 24), (68, 72, 24, 24), (92, 72, 24, 24)]

White = [(0, 0, 24, 24), (0, 24, 24, 24), (0, 48, 24, 24), (0, 72, 24, 24), (0, 96, 24, 24)]
Black = [(136, 0, 24, 24), (136, 24, 24, 24), (136, 48, 24, 24), (136, 72, 24, 24), (136, 96, 24, 24)]

board = [2, 0, 0,
         0, 0, 0,
         0, 0, 0]

board_num = [2,7,6,
             9,5,1,
             4,3,8]


mode=4
Sign = True

mode_4=False
mode_5=True

Test4=False
Test5=False

num1=False
num2=False
num3=False
num4=False
num5=False
num6=False
num7=False
num8=False
num9=False


Y_color=2 #Ai使用的棋子是什么颜色，1为白，2为黑，默认黑色
##------------------------  定义函数区  ---------------------------##


def Chess_test():
##返回棋盘棋谱##
    last_time = time.ticks_ms()
    board = []

    while True:
        img = sensor.snapshot()
        board = []
        num=0
        for i in chess:
            if time.ticks_ms() - last_time > 2000 :
               num+=1
            img.draw_rectangle(i, color=(200, 255, 255))
            w = img.find_blobs([white], roi=i)
            b = img.find_blobs([black], roi=i)
            x1 = i[0]
            y1 = i[1]

            if b:
                img.draw_cross(x1 + 12, y1 + 12, 10, color=(0, 100, 255), thickness=2, fill=0)
                if time.ticks_ms() - last_time > 2000 :
                    board.append(2)
                    if num == 9:
                        return board

            elif w:
                img.draw_cross(x1 + 12, y1 + 12, 10, color=(0, 255, 255), thickness=2, fill=0)
                if time.ticks_ms() - last_time > 2000 :
                    board.append(1)
                    if num == 9:
                        return board

            else:
                if time.ticks_ms() - last_time > 2000 :
                  board.append(0)
                  if num == 9:
                      return board

def convert_to_2d(board):

    two_d_board = []
    for r in range(3):
        row = board[r * 3:(r + 1) * 3]
        two_d_board.append(row)

    return two_d_board

def find_board_num(need_num,board_num,board):
        indices_num = []
        if need_num <= 0:
          return 555
        for idx, value in enumerate(board_num):
          if value == need_num:
              indices_num.append(idx)
        if not indices_num:
                return 555

        if board[indices_num[0]]== 0:
            return indices_num[0]
        else:
          return 555

def yi_er(num):
        if num <= 3:
            x = 0
            y = num
        elif num <= 6:
            x = 1
            y = num - 3
        else:
            x = 2
            y = num - 6
        return x*10+y

def EX_Will_Win_2(Y_color, board, board_num):
#检查AI在场上只有两个自己颜色的棋子的时候是否快要胜利
        indices = []
        indices_num = []

        for idx, value in enumerate(board):
            if value == Y_color:
                indices.append(idx)

        num = board_num[indices[0]]+board_num[indices[1]]
        need_num = 15 - num
        if need_num == board_num[indices[0]] or need_num == board_num[indices[1]]:
           return 555
        End_num = find_board_num(need_num,board_num,board)

        return End_num


def EX_Will_Win_3(Y_color, board,board_num):
#检查AI在场上只有三个自己颜色的棋子的时候是否快要胜利
        indices = []
        indices_num = []
        all_num1=True
        all_num2=True
        all_num3=True
        for idx, value in enumerate(board):
          if value == Y_color:
             indices.append(idx)

        num1 = board_num[indices[0]]+board_num[indices[1]]
        num2 = board_num[indices[0]]+board_num[indices[2]]
        num3 = board_num[indices[1]]+board_num[indices[2]]
        need_num1 = 15 - num1
        need_num2 = 15 - num2
        need_num3 = 15 - num3

        if need_num1 == board_num[indices[0]] or need_num1 == board_num[indices[1]]:
           all_num1 =False
        if need_num2 == board_num[indices[0]] or need_num2 == board_num[indices[2]]:
           all_num2=False
        if need_num3 == board_num[indices[1]] or need_num3 == board_num[indices[2]]:
           all_num3=False

        End_num1=End_num2=End_num3=555
        if all_num1:
           End_num1 = find_board_num(need_num1,board_num,board)
        if all_num2:
           End_num2 = find_board_num(need_num2,board_num,board)
        if all_num1:
           End_num3 = find_board_num(need_num3,board_num,board)

        if End_num1 != 555:
            return End_num1
        elif End_num2 != 555:
            return End_num2
        elif End_num3 != 555:
            return End_num3
        else:
         return 555

def EX_Will_Win_4(Y_color, board):
# 检查AI在场上有四个自己颜色的棋子的时候是否快要胜利
    indices = []
    for idx, value in enumerate(board):
        if value == 0:
            indices.append(idx)

    if indices:
        board[indices[0]] = Y_color
        if check_winner(board) == Y_color:
            return indices[0]
        board[indices[1]] = Y_color
        if check_winner(board) == Y_color:
            return indices[1]
    return 555



def check_winner(board):
##检查谁赢了比赛
    board_2 = convert_to_2d(board)
    for i in range(3):
        if board_2[i][0] == board_2[i][1] == board_2[i][2] != 0:
            return board_2[i][0]
        if board_2[0][i] == board_2[1][i] == board_2[2][i] != 0:
            return board_2[0][i]

    if board_2[0][0] == board_2[1][1] == board_2[2][2] != 0:
        return board_2[0][0]
    if board_2[0][2] == board_2[1][1] == board_2[2][0] != 0:
        return board_2[0][2]

    if all(board_2[i][j] != 0 for i in range(3) for j in range(3)):
        return 3
    return 0

def Win_3_num(Y_color, board):
        indices = []
        indices_num = []
        all_num1=True
        all_num2=True
        all_num3=True
        num=0
        for idx, value in enumerate(board):
          if value == Y_color:
             indices.append(idx)

        num1 = board_num[indices[0]]+board_num[indices[1]]
        num2 = board_num[indices[0]]+board_num[indices[2]]
        num3 = board_num[indices[1]]+board_num[indices[2]]
        need_num1 = 15 - num1
        need_num2 = 15 - num2
        need_num3 = 15 - num3

        if need_num1 == board_num[indices[0]] or need_num1 == board_num[indices[1]]:
           all_num1 =False
        if need_num2 == board_num[indices[0]] or need_num2 == board_num[indices[2]]:
           all_num2=False
        if need_num3 == board_num[indices[1]] or need_num3 == board_num[indices[2]]:
           all_num3=False

        End_num1=End_num2=End_num3=555
        if all_num1:
           End_num1 = find_board_num(need_num1,board_num,board)
        if all_num2:
           End_num2 = find_board_num(need_num2,board_num,board)
        if all_num1:
           End_num3 = find_board_num(need_num3,board_num,board)

        if End_num1 != 555:
            num+=1
        if End_num2 != 555:
           num+=1
        if End_num3 != 555:
           num+=1
        if num==0:
           return 555
        else:
           return num

def best_2(Y_color,board):
        indices = []
        for idx, value in enumerate(board):
            if value == 0:
               indices.append(idx)
        for i in range(min(len(indices), 4)):
            board[indices[i]] = Y_color
            if Win_3_num(Y_color, board) == 2:
               return indices[i]
            board[indices[i]] = 0

        return 555

def first(num,board,Y_color):
        board[num]=Y_color
        return board


def Four_Rect(board, Y_color):
    for i in [0, 2, 8, 6]:
        if board[i] == 0:
            return i

def Find_Four_Rect(board):
    for i in [0, 2, 8, 6]:
        if board[i] == 2:
           num+=1
    return num

def Test_move(Y_color, old_board, new_board):
    old_num = None
    new_num = None

    for i in range(9):
        if old_board[i] != new_board[i]:
            if old_board[i] == Y_color:
                old_num = i
            else:
                new_num = i

    if old_num is not None and new_num is not None:

        yb_uart.write(old_num)
        yb_uart.write(new_num)
    else:
        pass


def uartgo(num):
    str_data = str(num)
    byte_data = bytes(str_data, 'utf-8')
    yb_uart.write(byte_data)

#def find_qi(board,H_color):

##-------------------------------   定义结束   -----------------------------------##
fm.register(6, fm.fpioa.UART2_RX)
fm.register(8, fm.fpioa.UART2_TX)
yb_uart = UART(UART.UART2, 115200, 8, 0, 0, timeout=1000, read_buf_len=4096)


last_time = time.ticks_ms()
Level_4=1
Level_5=1

while True:

        #if time.ticks_ms() - last_time > 500:
        #   last_time = time.ticks_ms()
        #   yb_uart.write(write_bytes)

        if yb_uart.any():

            read_data = yb_uart.read()
            read_int = int(read_data.decode('utf-8')) ##进行解码处理，
            #print(received_int)
            #print(read_int)
            if read_int == 4:
                mode_4=True
                yb_uart.write("10")
                break

                #print("6")
            elif read_int == 5:
                mode_5=True
                break

                #print("7")
            else:
                pass

while mode_4:
        if yb_uart.any():                                ##获取串口数据
           read_data = yb_uart.read()
           read_int = int(read_data.decode('utf-8'))     ##进行解码处理

           if Level_4 == 1:                              ##人机黑棋先下的第一步
              new_board_1=[]
              new_board_1 = first(read_int - 1,board,2)  ##调用函数，接收串口返回数据后传到函数
              uartgo(read_int)
              Level_4+=1                                 ##进入下一步

           elif Level_4 == 2:
              new_board_2=[0,1,0,
                           0,2,0,
                           0,0,0]
              #new_board_2 = Chess_test()
              #Test_move(2, new_board_1, new_board_2)     ##第六问内容，检测棋子是否被移动，先注释
              if new_board_2[4]==0:                       ##判断中心点是否可下，可以下就下在中心点
                 new_board_2[4]==2
                 uartgo(5)

              else:
                num4_2 = Four_Rect(new_board_2, 2)   ##如果不可下，就下在四个边角其中一个上
                uartgo(num4_2 + 1)
              Level_4+=1



           elif Level_4 == 3:
              new_board_3=[2,1,0,
                           0,2,0,
                           0,0,1]
              #new_board_3 = Chess_test()
              #Test_move(2, new_board_2, new_board_3)
              W_W_num = EX_Will_Win_2(1, new_board_3,board_num)
              B_W_num = EX_Will_Win_2(2, new_board_3,board_num)
              if B_W_num != 555:                          ##检查黑棋是否可以直接获胜
                 new_board_3[B_W_num]=2
                 uartgo(B_W_num+1)
              elif  W_W_num != 555:
                 new_board_3[W_W_num]=2                   ##检查白棋是否可以直接获胜
                 uartgo(W_W_num+1)
              else:
                 best_num = best_2(2,new_board_3)         ##如果不可以直接获胜，找出必胜方法
                 print(best_num)
                 new_board_3[best_num] == 2
                 uartgo(best_num+1)
              Level_4+=1


           elif Level_4 == 4:
              new_board_4=[2,1,0,
                           2,2,1,
                           0,0,1]
              #new_board_4 = Chess_test()
              #Test_move(2, new_board_3, new_board_4)
              W_W_num = EX_Will_Win_3(1, new_board_4,board_num)
              B_W_num = EX_Will_Win_3(2, new_board_4,board_num)
              if B_W_num != 555:
                 new_board_4[B_W_num]=2
                 uartgo(B_W_num+1)
              elif  W_W_num != 555:
                 new_board_4[W_W_num]=2
                 uartgo(W_W_num+1)
              else:
                 print("4_4 Error!")

           else:
              print("4 Error ! ")








yb_uart.deinit()
